/*
当实现泛型接口时，我们可以选择在实现类明确泛型类型，或是继续使用此泛型，让具体创建的对象来确定类型
下面是的例子是在实现接口的时候直接明确类型，明确了类型后，后面使用明确的类型
 */
package com.Generics5;

public class Score2 implements ScoreInterface<String> {  //在实现接口时明确类型
    String name;
    int id;
    String score;  //这里使用明确的类型String

    public Score2(String name, int id, String score){
        this.name = name;
        this.id = id;
        this.score = score;
    }

    //按ctrl+O，选择getScore()和setScore() 方法重写
    @Override
    public String getScore() {
        return null;
    }

    @Override
    public void setScore(String s) {

    }

    /*
    思考一个问题，既然继承后明确了泛型类型，那为什么@Override不会出现错误呢？重写的条件是需要和父类的返回值类型、形式参数一致，
    而泛型的默认原始类型是Object类型，子类明确后变为String类型，这显然不能满足重写的条件，但为什么依然能编译通过？
     */
    /* 对Score2.class反编译的结果，发现对两个Override的方法反编译出4个方法，每个方法出现两次，
    分别对应java.lang.String和java.lang.Object，其中Object对应重写父类的方法，Object接受String类型的这个方法

    通过反编译进行观察，实际上是编译器帮我们生成了两个Object类型的方法，去调用我们写的方法，通过这种方式支持重写。
    这两个Object方法叫桥接方法

    javap -l .\Score2.class
        Compiled from "Score2.java"
        public class com.Generics5.Score2 implements com.Generics5.ScoreInterface<java.lang.String> {
          java.lang.String name;

          int id;

          java.lang.String score;

          public com.Generics5.Score2(java.lang.String, int, java.lang.String);
            LineNumberTable:
              line 12: 0
              line 13: 4
              line 14: 9
              line 15: 14
              line 16: 19
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0      20     0  this   Lcom/Generics5/Score2;
                  0      20     1  name   Ljava/lang/String;
                  0      20     2    id   I
                  0      20     3 score   Ljava/lang/String;

          public java.lang.String getScore();
            LineNumberTable:
              line 21: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       2     0  this   Lcom/Generics5/Score2;

          public void setScore(java.lang.String);
            LineNumberTable:
              line 27: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       1     0  this   Lcom/Generics5/Score2;
                  0       1     1     s   Ljava/lang/String;

          public void setScore(java.lang.Object);
            LineNumberTable:
              line 7: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       9     0  this   Lcom/Generics5/Score2;

          public java.lang.Object getScore();
            LineNumberTable:
              line 7: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       5     0  this   Lcom/Generics5/Score2;
        }

     */
}
